package com.spring;

import org.apache.logging.log4j.web.Log4jServletFilter;
import org.comet4j.core.CometServlet;
import org.springframework.orm.hibernate4.support.OpenSessionInViewFilter;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.filter.DelegatingFilterProxy;
import org.springframework.web.servlet.DispatcherServlet;

import javax.servlet.*;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by charles on 15-1-24.
 */
public class Initializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        servletContext.setInitParameter("webAppRootKey", "gradlePush.root");
        addSpringAppListener(servletContext);
        addLog4jListener(servletContext);
        addLog4jFilter(servletContext);
        addComet4JListener(servletContext);
        addComet4JServlet(servletContext);
        addComet4JPushListener(servletContext);
        addCharacterEncodingFilter(servletContext);
        addOpenSessionInViewFilter(servletContext);
        addSpringMvcServlet(servletContext);
        addShiroFilter(servletContext);
       /* servletContext.getServletRegistration("default").addMapping(
                "*.css", "*.js", "*.gif", "*.jpg", ".png", "*eot", "*.svg", "*.ttf", "*.woff"
        );*/
    }

    /**
     * 增加 spring listener
     *
     * @param servletContext ServletContext
     */
    private void addSpringAppListener(ServletContext servletContext) {
        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
        rootContext.register(AppConfig.class);
        servletContext.addListener(new ContextLoaderListener(rootContext));
    }

    /**
     * 增加 log4j listener
     *
     * @param servletContext ServletContext
     */
    private void addLog4jListener(ServletContext servletContext) {
        servletContext.addListener(org.apache.logging.log4j.web.Log4jServletContextListener.class);
    }

    /**
     * 增加 log4j filter
     *
     * @param servletContext ServletContext
     */
    private void addLog4jFilter(ServletContext servletContext) {
        FilterRegistration.Dynamic log4jServletFilter = servletContext.addFilter("log4jFilter", Log4jServletFilter.class);
        log4jServletFilter.addMappingForUrlPatterns(
                EnumSet.of(DispatcherType.FORWARD, DispatcherType.REQUEST, DispatcherType.INCLUDE, DispatcherType.ERROR),
                false, "/*"
        );
        Map<String, String> parameters = new HashMap<>();
        parameters.put("log4jContextName", "gradlePush");
        parameters.put("log4jConfiguration", "/WEB-INF/classes/log4j2.xml");
        log4jServletFilter.setInitParameters(parameters);
        /*servletContext.setInitParameter("log4jContextName", "gradlePush");
        servletContext.setInitParameter("log4jConfiguration", "/WEB-INF/classes/log4j2.xml");*/
    }

    /**
     * 增加 comet4J listener
     *
     * @param servletContext ServletContext
     */
    private void addComet4JListener(ServletContext servletContext) {
        servletContext.addListener(org.comet4j.core.CometAppListener.class);
    }

    /**
     * 增加 comet4J servlet
     *
     * @param servletContext ServletContext
     */
    private void addComet4JServlet(ServletContext servletContext) {
        ServletRegistration.Dynamic cometServlet = servletContext.addServlet("CometServlet", CometServlet.class);
        cometServlet.addMapping("/conn");
    }

    /**
     * 增加 comet4j push listener
     *
     * @param servletContext ServletContext
     */
    private void addComet4JPushListener(ServletContext servletContext) {
        servletContext.addListener(com.gradledemo.push.server.PushServerListener.class);
    }

    /**
     * 字符编码 Filter
     *
     * @param servletContext ServletContext
     */
    private void addCharacterEncodingFilter(ServletContext servletContext) {
        FilterRegistration.Dynamic characterEncodingFilter = servletContext.addFilter("CharacterEncodingFilter", CharacterEncodingFilter.class);
        Map<String, String> parameters = new HashMap<>();
        parameters.put("encoding", "UTF-8");
        parameters.put("forceEncoding", "true");
        characterEncodingFilter.setInitParameters(parameters);
        characterEncodingFilter.addMappingForUrlPatterns(null, false, "/*");
    }

    /**
     * 防止 Hibernate Session 过期的 Filter。
     *
     * @param servletContext ServletContext
     */
    private void addOpenSessionInViewFilter(ServletContext servletContext) {
        FilterRegistration.Dynamic opensessioninview = servletContext.addFilter("opensessioninview", OpenSessionInViewFilter.class);
        opensessioninview.addMappingForUrlPatterns(null, false, "/*");
    }

    /**
     * 增加 spring mvc filter
     *
     * @param servletContext ServletContext
     */
    private void addSpringMvcServlet(ServletContext servletContext) {
        AnnotationConfigWebApplicationContext mvcContext = new AnnotationConfigWebApplicationContext();
        mvcContext.register(MvcConfig.class);
//        mvcContext.refresh();
        ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher",
                new DispatcherServlet(mvcContext));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("*.htm", "*.json", "*.xml");
    }

    /**
     * 权限过滤的配置 Filter
     *
     * @param servletContext ServletContext
     */
    private void addShiroFilter(ServletContext servletContext) {
        FilterRegistration.Dynamic shiroFilter = servletContext.addFilter("shiroFilter", DelegatingFilterProxy.class);
        Map<String, String> params = new HashMap<>();
        params.put("targetFilterLifecycle", "true");
        shiroFilter.setInitParameters(params);
        shiroFilter.addMappingForUrlPatterns(EnumSet.of(
                DispatcherType.REQUEST,
                DispatcherType.INCLUDE,
                DispatcherType.FORWARD,
                DispatcherType.ERROR
        ), false, "*.htm");
    }
}
